package com.iwithlong.service.impl;

import com.alibaba.fastjson.JSON;
import com.imesne.assistant.common.exception.ImesneException;
import com.iwithlong.service.ActivityService;
import com.iwithlong.service.WeixinService;
import com.iwithlong.utils.JsonUtil;
import com.iwithlong.vo.ActivityVo;
import com.iwithlong.weixincustomhandler.DefaultWeixnCustomHandler;
import com.iwithlong.weixincustomhandler.EventWeixinCustomHandler;
import com.iwithlong.weixincustomhandler.TextWeixinCustomHandler;
import com.iwithlong.weixincustomhandler.WeixinCustomHandler;
import com.ktanx.platform.setting.kit.SettingKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

/**
 * Created by xiexiaohan on 2017/12/12.
 */
@Service
@Slf4j
public class WeixinServiceImpl implements WeixinService {

    @Value("${weixinpublicurl:null}")
    private String weixinUrl;

    @Value("${weixingettoken:null}")
    private String getTokenUrl;

    //公众号secret
    @Value("${weixinpublicsecret:null}")
    private String publicsecret;

    //地图secret
    @Value("${weixinmapsecret:null}")
    private String mapsecret;

    @Value("${weixingetmap:null}")
    private String getMapUrl;

    @Value("${proxyurl:null}")
    private String proxyUrl;

    @Value("${machiningtagparam:null}")
    private String machiningTagParam;

    @Value("${weburl:null}")
    private String webUrl;

    @Value("${weixincustomurl:null}")
    private String weixinCustomUrl;

//    @Value("${weixincustomtoken:null}")
//    private String weixinCustomToken;

    @Value("${appid:null}")
    private String weixinAppId;

    private static final String[] appErrCodeStrs = new String[]{"-1","40001","40002","40003","45015","45047","48001"};

    @Resource
    private ActivityService activityService;

    //需要进行加工的标签属性
    private Set<String> machiningTagParams;

    private String access_token;

    @Override
    public Object requestAccessToken(String grant_type, String appid, int offset,int count) {
        if(access_token==null){
            String param = "grant_type="+grant_type+"&appid="+appid+"&secret="+publicsecret;
            String tokenJsonStr = sendGet(getTokenUrl,param);
            Map accessTokenMap = (Map) JSON.parse(tokenJsonStr);
            if(accessTokenMap.get("access_token")==null){
                return JSON.parse(tokenJsonStr);
            }
            access_token = accessTokenMap.get("access_token").toString();
        }
        Object result = sendToken(access_token,offset,count);
        Map map = (Map) result;
        Object errcode = map.get("errcode");
        if(errcode!=null&& (StringUtils.equals(errcode.toString(),"42001")||StringUtils.equals(errcode.toString(),"480001")||StringUtils.equals(errcode.toString(),"48001"))){
            String param = "grant_type="+grant_type+"&appid="+appid+"&secret="+publicsecret;
            String tokenJsonStr = sendGet(getTokenUrl,param);
            Map accessTokenMap = (Map) JSON.parse(tokenJsonStr);
            access_token = accessTokenMap.get("access_token").toString();
            if(accessTokenMap.get("access_token")==null){
                return JSON.parse(tokenJsonStr);
            }
            result = sendToken(access_token,offset,count);
        }
        return result;
    }

    @Override
    public String requestWeixinPublic(String url) {
        String context  = sendGet(url,null);
        if(machiningTagParams==null){
            initMachiningTageParams();
        }
        String addUrl = webUrl + proxyUrl + "?url=";
        log.info("addUrl:"+addUrl);
        for (String tagParam : machiningTagParams) {
            if(tagParam.startsWith(" data-src")||tagParam.startsWith("data-src")){
                context = context.replaceAll(tagParam+"http"," src=\""+addUrl+"http");
                context = context.replaceAll(tagParam+"//"," src=\""+addUrl+"https://");
            }else {
                context = context.replaceAll(tagParam+"http",tagParam+addUrl+"http");
                context = context.replaceAll(tagParam+"//",tagParam+addUrl+"https://");
            }
            log.info("替换的字符："+tagParam);
        }
        log.info("文本内容："+context);
        return context;
    }

    private void initMachiningTageParams() {
        machiningTagParams = new HashSet<>();
        String[] params = machiningTagParam.split(",");
        for (String param : params) {
            machiningTagParams.add(param);
        }
        log.info("初始化加工标签属性，params:[]"+machiningTagParams.toString());
    }


    @Override
    public Object requestWeixinJsonObject(String url) {
        String data = sendGet(url,null);
        return JSON.parse(data);
    }

    @Override
    public Object requestMapData(String appid, String js_code, String grant_type) {
        StringBuilder param = new StringBuilder();
        param.append("appid=").append(appid).append("&js_code=").append(js_code).append("&grant_type=").append(grant_type)
                .append("&secret=").append(mapsecret);
        return JSON.parse(sendGet(getMapUrl,param.toString()));
    }

    @Override
    public void dealWithAppRequest(HttpServletRequest request, HttpServletResponse response) {
        try{
            log.info("开始将请求转josn");
            String requestJson = getRequestJson(request);
            if(StringUtils.isNotBlank(requestJson)){
                log.info("requestJson:"+requestJson);
                Map<String,Object> requestMap = JsonUtil.jsonToMap(requestJson);
                log.info("requestMap:"+requestMap);
                //处理请求数据并转换成发送给微信小程序的数据包
//                WeixinCustomHandler weixinCustomHandler = getWeixnCustomHandler(requestMap);
//                Map<String,Object> map = weixinCustomHandler.dealWithJsonRequest(requestMap);
                Map<String,Object> map = dealWithJsonRequest(requestMap);
                if(map!=null){
                    //发送给微信小程序客服的数据包
                    String jsonSendToCustom = JsonUtil.beanToJson(map);
                    log.info("发送给微信服务器json数据包:"+jsonSendToCustom);
                    postToWeixinCustom(jsonSendToCustom);
                }
            }
            response.getWriter().write("");
        }catch (Exception e){
            log.error("微信小程序客服信息处理失败");
            try {
                response.getWriter().write("false");
            } catch (IOException e1) {
                log.error("微信小程序客服信息处理失败");
            }
        }
    }

    public Map<String, Object> dealWithJsonRequest(Map<String, Object> map) {
        String event = String.valueOf(map.get("Event"));
        if(!StringUtils.equals("user_enter_tempsession",event)){
            return null;
        }
        Map<String,Object> result = new HashMap<>();
        result.put("touser",map.get("FromUserName"));
        String sessionFrom = String.valueOf(map.get("SessionFrom"));
        if(StringUtils.equals(sessionFrom,"enter")){
            result.put("msgtype","text");
            Map<String,String> text = new HashMap<>();
            String content = SettingKit.getValue("weixinAppWelcomeWords");
            if(StringUtils.isBlank(content)){
                return null;
            }
            text.put("content",content);
            result.put("text",text);
        }else if (StringUtils.equals(sessionFrom,"follow")){
            result.put("msgtype","link");
            Map<String,String> link = new HashMap<>();
            link.put("title","爱常伴");
            link.put("description","爱常伴的主页");
            link.put("thumb_url",webUrl+ "/img/ichangban.jpeg");
            link.put("url",SettingKit.getValue("weixinPublicIndexUrl"));
            result.put("link",link);
        }else {
            ActivityVo activity = activityService.findById(Long.valueOf(sessionFrom));
            if(activity==null){
                result.put("msgtype","text");
                Map<String,String> text = new HashMap<>();
                text.put("content","该活动不存在");
                result.put("text",text);
                return result;
            }
            String picUrl = activityService.findActivityFirstPicUrl(activity.getActivityId());
            result.put("msgtype","link");
            Map<String,String> link = new HashMap<>();
            link.put("title",activity.getName()+"购票");
            link.put("description",activity.getBrief());
            link.put("thumb_url",webUrl+"/upload/get/image.json?url="+picUrl);
            link.put("url",activity.getTicketUrl());
            result.put("link",link);
        }
        return result;
    }

    private void postToWeixinCustom(String jsonSendToCustom) throws Exception {
        Object errCode = null;
        int count = 0;
        do{
            if(access_token==null||errCode!=null){
                log.info("重新获取token");
                String param = "grant_type=client_credential"+"&appid="+weixinAppId+"&secret="+mapsecret;
                String tokenJsonStr = sendGet(getTokenUrl,param);
                Map accessTokenMap = (Map) JSON.parse(tokenJsonStr);
                if(accessTokenMap.get("access_token")==null){
                    log.info("获取token失败");
                    return;
                }
                access_token = accessTokenMap.get("access_token").toString();
            }
            HttpClient client = new DefaultHttpClient();
            HttpPost post = new HttpPost(weixinCustomUrl+"?access_token="+access_token);
            log.info("请求地址："+weixinCustomUrl+"?access_token="+access_token);
            post.setHeader("Content-Type", "application/json");
            post.addHeader("Authorization", "Basic YWRtaW46");
            StringEntity s = new StringEntity(jsonSendToCustom,"utf-8");
            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                    "application/json"));
            post.setEntity(s);
            // 发送请求
            HttpResponse httpResponse = client.execute(post);
            // 获取响应输入流
            InputStream inStream = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    inStream, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null)
                strber.append(line + "\n");
            inStream.close();
            String result = strber.toString();
            log.info("返回的数据"+result);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            } else {
                log.info("请求微信小程序客服服务器失败");
                return;
            }
            Map map = (Map) JSON.parse(result);
            errCode = map.get("errcode");
            count++;
        }while (errCode!=null&&StringUtils.startsWithAny(errCode.toString(),appErrCodeStrs)&&count<2);
    }

    private WeixinCustomHandler getWeixnCustomHandler(Map<String, Object> requestMap) {
        String type = String.valueOf(requestMap.get("MsgType"));
        log.info("类型："+type);
        switch (type){
            case "text":
                return new TextWeixinCustomHandler();
            case "event":
                return new EventWeixinCustomHandler();
            default:
                return new DefaultWeixnCustomHandler();
        }
    }


    private String getRequestJson(HttpServletRequest request) throws IOException {

        ServletInputStream inputStream = request.getInputStream();
        StringWriter sw = new StringWriter();
        IOUtils.copy(inputStream,sw,"utf-8");
        return sw.toString();
    }

    private Object sendToken(String access_token,int offset,int count){
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(weixinUrl+"?access_token="+access_token);

        post.setHeader("Content-Type", "application/json");
        post.addHeader("Authorization", "Basic YWRtaW46");
        String result ;

        try {

            JSONObject jsonParam = new JSONObject();
//            jsonParam.put("access_token", access_token);// 红谷滩新闻资讯，channelId 77
            jsonParam.put("type","news");
            jsonParam.put("offset",offset);
            jsonParam.put("count",count);
            StringEntity s = new StringEntity(jsonParam.toString(),"utf-8");
            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                    "application/json"));
            post.setEntity(s);

            // 发送请求
            HttpResponse httpResponse = client.execute(post);

            // 获取响应输入流
            InputStream inStream = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    inStream, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null)
                strber.append(line + "\n");
            inStream.close();

            result = strber.toString();
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

//                System.out.println("请求服务器成功，做相应处理");

            } else {

                throw new ImesneException("请求微信公众号失败");

            }


        } catch (Exception e) {
            throw new ImesneException("请求微信公众号失败");
        }

        return JSON.parse(result);
    }



    private String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url;
            if(StringUtils.isNotBlank(param)){
                urlNameString += "?"+param;
            }else {

            }

            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            throw new ImesneException("请求数据失败");
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }
}
